
#include "Engine.h"
#include "Input.h"
#include "Camera.h"
#include "Geometry.h"
#include "Entity.h"
#include "TEString.h"

#define INITSTATE(X) STATE(X) *_STATE(X) = new STATE(X)()
#define STATECALL(X) void STATE(X)::Render()
//#define FLY_MODE

INITSTATE(MainMenu);
INITSTATE(CreateGame);
INITSTATE(JoinGame);
INITSTATE(Settings);
INITSTATE(_3D);
INITSTATE(Loading);

STATECALL(MainMenu)
{
	// Clears the back buffer screen
	engine.direct3DRenderer->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, __black, 1.0f, 0);

	ushort wMiddle = engine.camera->Width() / 2;
	ushort hMiddle = engine.camera->Height() / 2;

	static uchar i = 0;

	// Begin rendering
	engine.BeginRender();

		// No lights
		engine.direct3DRenderer->SetRenderState(D3DRS_LIGHTING, FALSE);

		// Draw Menu Text
		engine.DrawStringLarge(wMiddle-90, 80, L"Target Engine", __red);
		engine.DrawStringLarge(wMiddle-85, hMiddle-80, L"Create Game", (i == 0 ? __green : __white));
		engine.DrawStringLarge(wMiddle-68, hMiddle-30, L"Join Game",   (i == 1 ? __green : __white));
		engine.DrawStringLarge(wMiddle-50, hMiddle+20, L"Settings",    (i == 2 ? __green : __white));
		engine.DrawStringLarge(wMiddle-22, hMiddle+70, L"Exit",        (i == 3 ? __green : __white));

	// End Rendering
	engine.EndRender();

	// Switch the back buffer forward
	engine.SwitchBuffers();

	// Scan the keys & mouse
	input.UpdateDevices();

	// Keys
	if(input.KeyPressedOnce(DIK_UP))
		if(i-- < 1) i = 3;
	if(input.KeyPressedOnce(DIK_DOWN))
		if(++i > 3) i = 0;
	if(input.KeyPressedOnce(DIK_ESCAPE))
		PostQuitMessage(0);
	if(input.KeyPressedOnce(DIK_RETURN))
	{
		switch(i)
		{
		case 0: 
			engine.state = _STATE(_3D);
			//engine.state = _STATE(CreateGame);
			break;
		case 1: 
			engine.state = _STATE(_3D);
			//engine.state = _STATE(JoinGame);
			break;
		case 2: 
			//engine.state = _STATE(_3D);
			engine.state = _STATE(Settings);
			break;
		case 3: 
			PostQuitMessage(0);
			break;
		}
	}

	#ifdef SKIP_MENU
	engine.state = _STATE(_3D);
	#endif
}

STATECALL(CreateGame)
{
}

STATECALL(JoinGame)
{
}

STATECALL(Settings)
{
	static bool changed = false;

	// Clears the back buffer screen
	engine.direct3DRenderer->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, __black, 1.0f, 0);

	ushort wMiddle = engine.camera->Width() / 2;
	ushort hMiddle = engine.camera->Height() / 2;

	static uchar i = 0;

	// Begin rendering
	engine.BeginRender();

		// No lights
		engine.direct3DRenderer->SetRenderState(D3DRS_LIGHTING, FALSE);

		// Draw Menu Text
		engine.DrawStringLarge(wMiddle-60, 80, L"Settings", __red);
		engine.DrawStringLarge(wMiddle-85, hMiddle-80, L"Player name",																							(i == 0 ? __green : __white));
		engine.DrawStringLarge(wMiddle-72, hMiddle-30, L"Resolution",																								(i == 1 ? __green : __white));
		engine.DrawStringLarge(wMiddle-70, hMiddle+20, engine.camera->FullScreen() ? L"Fullscreen" : L"Windowed",		(i == 2 ? __green : __white));
		engine.DrawStringLarge(wMiddle-75, hMiddle+70, L"Detail level",																							(i == 3 ? __green : __white));
		engine.DrawStringLarge(wMiddle-120, hMiddle+170, L"Save and Return",																				(i == 4 ? __green : __white));

	// End Rendering
	engine.EndRender();

	// Switch the back buffer forward
	engine.SwitchBuffers();

	// Scan the keys & mouse
	input.UpdateDevices();

	// Keys
	if(input.KeyPressedOnce(DIK_UP))
		if(i-- < 1) i = 4;
	if(input.KeyPressedOnce(DIK_DOWN))
		if(++i > 4) i = 0;
	if(input.KeyPressedOnce(DIK_ESCAPE))
		engine.state = _STATE(MainMenu);
	if(input.KeyPressedOnce(DIK_RETURN))
	{
		switch(i)
		{
		case 0: 
			//engine.state = _STATE(_3D);
			//engine.state = _STATE(CreateGame);
			break;
		case 1: 
			//engine.state = _STATE(_3D);
			//engine.state = _STATE(JoinGame);
			break;
		case 2: 
			engine.camera->fullscreen = !engine.camera->fullscreen;
			changed = true;
			//engine.state = _STATE(_3D);
			//engine.state = _STATE(Settings);
			break;
		case 3: 
			//engine.state = _STATE(_3D);
			break;
		case 4:
			if (changed)
			{
				if (!engine.WriteSettings()) PostQuitMessage(0);
				changed = false;
			}
			engine.state = _STATE(MainMenu);
		}
	}

	#ifdef SKIP_MENU
	engine.state = _STATE(_3D);
	#endif
}

STATECALL(_3D)
{
	// Clears the back buffer screen
	//engine.direct3DRenderer->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, __black, 1.0f, 0);
	if(FAILED(engine.direct3DRenderer->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, __lightgray, 1.0f, 0)))
				MessageBox(0, L"Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, __lightgray, 1.0f, 0)", L"Failure", 0);

	// Begin rendering
	engine.BeginRender();

		// Load the lights
		#ifdef USE_LIGHTS
		engine.LoadLights();
		#endif

		// Set render number back to zero
		engine.rVertices = 0;
		engine.rFaces = 0;

		// Clear old normals
		if(Geometry::updateNormals)
			Geometry::normals.clear();

		// Render the scene
		if(engine.renderWireframe)   engine.renderFlag = 0;
		else if(engine.renderPoints) engine.renderFlag = 1;
		else                         engine.renderFlag = 2;

		// Update all positions / rotations
		engine.scene->UpdateTransform();

		#ifdef DUAL_RENDER
			#ifdef USE_CULLING
			engine.direct3DRenderer->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
			#endif
		engine.scene->Render();
			#ifdef USE_CULLING
			engine.direct3DRenderer->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
			#endif
		#endif
		engine.scene->Render();
		engine.RenderBillboards();

		// Render Other stuff
		engine.LoadMatrices(engine.scene->WorldMatrix());
		engine.RenderNormals();
		engine.RenderBBoxes();

		// Write Text
		engine.DrawMessages();

		// Draws some text
		engine.camera->DrawCameraStats();
		engine.DrawStats();

	// End rendering
	engine.EndRender();

	// Switch the back buffer forward
	engine.SwitchBuffers();

	// Scan the keys & mouse
	input.UpdateDevices();

	// Uses the command window
	if(engine.commandActive) engine.CommandWindow();
	else
	{
		// Process engine keys
		engine.ProcessKeys();

		// Movement keys
		#ifdef FLY_MODE
		engine.camera->MoveCamera();
		#else
		engine.camera->FirstPersonMovement();
		engine.player.KeyResponse();
		#endif
	}
}

STATECALL(Loading)
{
}
